#include "Debug.h"
#include <assert.h>
#include "TestFactory.h"

#ifdef WIN32
#include <stdarg.h>
#include <stdio.h>
#include <tchar.h>
#endif

namespace AllTing
{

namespace Test
{

Debug::~Debug()
{
}

void Debug::Writer(IWritable* pWriter)
{
	assert(pWriter);
	if(Null == pWritable_)
	{
		pWritable_ = pWriter;
	}
}

void Debug::ActiveTest(Testable* pActiveTest)
{
	pActiveTest_ = pActiveTest;
}

const Testable* Debug::ActiveTest()
{
	return pActiveTest_;
}

void Debug::Assert(Bool bCondition, const Char* pszFile, UInt32 nLine) const
{
	++nAssert_;
	if(False == bCondition)
	{
		assert(pWritable_);
		assert(pActiveTest_);
		assert(pszFile);

		pActiveTest_->Error(pszFile, nLine);
/*
		_sntprintf(szBuffer_, DEBUG_MAX_LOG_BUFFER, L"%s(%u) : Failed to assert condition\n"), pszFile, nLine);

		pWritable_->Write(szBuffer_);
*/
	}
}

UInt32 Debug::Log(const Char* pszFormat, ...) const
{
    va_list args;
	va_start(args, pszFormat);
    
#ifdef WIN32
#if _MSC_VER > 1300
	UInt32 nLen = _vstprintf_s(szBuffer_, DEBUG_MAX_LOG_BUFFER, pszFormat, args) + sizeof(Char);
#else
	UInt32 nLen = _vstprintf(szBuffer_, pszFormat, args) + sizeof(Char);
#endif
#else
	UInt32 nLen = vswprintf(szBuffer_, DEBUG_MAX_LOG_BUFFER, pszFormat, args) + sizeof(Char);
#endif
	
	szBuffer_[nLen] = 0x00;
	
	UInt32 nRet = pWritable_->Write(szBuffer_);
    
	va_end(args);
    
	return nRet;
}
    
    
Bool Debug::Report()
{
    TestConstIterator itStart = TestFactory::Instance()->BeginTest();
    TestConstIterator itEnd = TestFactory::Instance()->EndTest();
    
    UInt32 nTestCount = TestFactory::Instance()->Size();
    UInt32 nFailedTest = 0;
    UInt32 nFailedAssert = 0;
    
    for(; itStart!=itEnd; ++itStart)
    {
        AssertConstIterator itAssertStart = (*itStart)->BeginFailedAssert();
        AssertConstIterator itAssertEnd = (*itStart)->EndFailedAssert();
        
        if(itAssertStart != itAssertEnd)
            ++nFailedTest;
        
        for(; itAssertStart!=itAssertEnd; ++itAssertStart)
        {
            if(False == itAssertStart->strFile.empty() && 0 < itAssertStart->nLine)
            {
#ifdef WIN32
	            Log(L"%s(%u) : Failed %s test\n", 
                    itAssertStart->strFile.c_str(), itAssertStart->nLine, (*itStart)->Name());
#else
                Log(L"%S(%u) : Failed %S test\n", 
                    itAssertStart->strFile.c_str(), itAssertStart->nLine, (*itStart)->Name());
#endif
                ++nFailedAssert;
            }
        }
    }
    
    Log(L"\r\n============================================================================\r\n");
    Log(L"Done - %u tests(%u asserts), %u succeeded(%u asserts), %u failed(%u asserts)", 
        nTestCount, nAssert_, nTestCount-nFailedTest, nAssert_-nFailedAssert, nFailedTest, nFailedAssert);
    Log(L"\r\n============================================================================\r\n");
    
    return True;
}

}	// namespace Test
}	// namespace AllTing